package com.dkm.shiro;

import java.util.Date;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.dkm.entity.Permission;
import com.dkm.entity.Role;
import com.dkm.entity.Users;
import com.dkm.service.UsersService;
import com.dkm.util.EncryptionUtil;

public class CustomRealm extends AuthorizingRealm {

	@Autowired
	private UsersService usersService;
	/**
	 * 授权（赋予权限）
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		System.out.println("授权authorization");
		
		//获取操作主体
		Users user=(Users) principalCollection.getPrimaryPrincipal();
		
		//让shiro知道主体拥有哪些权限
		SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
		for(Role role:user.getRoles()) {
			//告诉shiro这个用户拥有哪些角色
			simpleAuthorizationInfo.addRole(role.getRole_name());
			
			for(Permission permission:role.getPermissions()) {
				//告诉shiro用户有哪些权限
				simpleAuthorizationInfo.addStringPermission(permission.getPermission_value());
			}
		}
		
		return simpleAuthorizationInfo;
	}

	/**
	 * 认证（登录）
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		
		UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken) authenticationToken;
		//获取前台输入的登录名和密码
		String login_name=usernamePasswordToken.getUsername();
		String password=String.valueOf(usernamePasswordToken.getPassword());
		
		//String login_name=authenticationToken.getPrincipal().toString();
		//String password=authenticationToken.getCredentials().toString();
		
		System.out.println("password>="+password);
		//使用MD5对前台的密码加密并加盐
		String encryptionStr=EncryptionUtil.encryption(login_name, password);
		
		
		//根据登录名查询数据库中的用户信息
		Users user=usersService.findByLogin_name(login_name);
		
		//System.out.println("前台密码》"+String.valueOf(token.getPassword()));
		//判断用户是否存在
		if(user==null) {
			return null;
		}else if(user.getIs_lockout().equals("是")) {
			//抛出锁定异常
			throw new LockedAccountException("用户已被锁定");
		}
		else{
			System.out.println("数据库密码>="+user.getPassword());
			//判断密码是否正确
			if(!user.getPassword().equals(encryptionStr)) {
				System.out.println("incorrect credentials!");
				
				//如果该实行为空设置0
				if(user.getPassword_wrong_num()==null) {
					user.setPassword_wrong_num(0);
				}
				//设置密码错误次数+1
				user.setPassword_wrong_num(user.getPassword_wrong_num()+1);
				
				//如果错误次数大于等于5锁定用户
				if(user.getPassword_wrong_num()>=5) {
					
					//锁定用户
					user.setIs_lockout("是");
					user.setLock_time(new Date());
				}
				//执行修改
				usersService.saveAndFlushUser(user);
				System.out.println("密码不通过");
				//抛出错误凭证异常
				throw new IncorrectCredentialsException("密码错误！");
			}else {
				//密码正确设置登录时间
				user.setLast_login_time(new Date());
				//执行修改
				usersService.saveAndFlushUser(user);
				System.out.println("密码通过");
			}
			
	        /*
			 * 参数：
			 * 1操作的主体，或传主体的用户名
			 * 2主体密码
			 * 3当前的realm对象
			 */
			SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
					user,user.getPassword(),getName());
			
//			SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
//					user, user.getPassword(), ByteSource.Util.bytes(user.getLogin_name()), getName());
			return authenticationInfo;
		}
	}

}
